package com.hwd.srb.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hwd.srb.common.exception.Assert;
import com.hwd.srb.common.result.ResponseEnum;
import com.hwd.srb.common.util.LendNoUtils;
import com.hwd.srb.core.enmu.TransTypeEnum;
import com.hwd.srb.core.hfb.FormHelper;
import com.hwd.srb.core.hfb.HfbConst;
import com.hwd.srb.core.hfb.RequestHelper;
import com.hwd.srb.core.mapper.LendItemMapper;
import com.hwd.srb.core.mapper.UserAccountMapper;
import com.hwd.srb.core.pojo.bo.TransFlowBO;
import com.hwd.srb.core.pojo.entity.Lend;
import com.hwd.srb.core.pojo.entity.LendItem;
import com.hwd.srb.core.pojo.entity.UserAccount;
import com.hwd.srb.core.pojo.vo.InvestVo;
import com.hwd.srb.core.service.LendItemService;
import com.hwd.srb.core.service.LendService;
import com.hwd.srb.core.service.TransFlowService;
import com.hwd.srb.core.service.UserBindService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author 黄伟东/Victor
 * @since 2022-03-10
 */
@Service
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {

    @Resource
    private LendService lendService;

    @Resource
    private UserBindService userBindService;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private TransFlowService transFlowService;

    /**
     * 会员投资提交数据，调用hfb接口，生成并返回投资表单
     *
     * @param investVO 投资信息，包含lendId，investAmount
     * @return java.lang.String
     */
    @Override
    public String commitInvest(InvestVo investVO) {

        // 获取投资参数
        BigDecimal investAmount = new BigDecimal(investVO.getInvestAmount());

        // 获取相关表信息
        Lend lend = lendService.getById(investVO.getLendId());

        //标的不能超卖：(已投金额 + 本次投资金额 )>=标的金额（超卖）TODO

        //账户可用余额充足：当前用户的余额 >= 当前用户的投资金额（可以投资）TODO

        // 生成投标lend_item数据
        LendItem lendItem = new LendItem();
        String lendItemNo = LendNoUtils.getLendItemNo();
        lendItem.setLendItemNo(lendItemNo);// 投资条目编号（一个Lend对应一个或多个LendItem）
        lendItem.setLendId(investVO.getLendId());// 标的id
        lendItem.setInvestUserId(investVO.getInvestUserId());// 用户id
        lendItem.setInvestName(investVO.getInvestName());// 用户名字
        lendItem.setInvestAmount(investAmount);// 投资金额
        lendItem.setLendYearRate(lend.getLendYearRate());// 年华利率
        lendItem.setInvestTime(LocalDateTime.now());// 投资时间
        lendItem.setLendStartDate(lend.getLendStartDate());// 标的开始时间
        lendItem.setLendEndDate(lend.getLendEndDate());// 标的结束时间
        lendItem.setRealAmount(new BigDecimal("0"));
        lendItem.setStatus(0);// 默认状态

        BigDecimal interestCount = lendService.getInterestCount(
                investAmount, lend.getLendYearRate(), lend.getPeriod(),
                lend.getReturnMethod().getReturnMethod());
        lendItem.setExpectAmount(interestCount);// 投资预期收益

        //执行插入
        baseMapper.insert(lendItem);
        String bindCode = userBindService.getBindCodeByUserId(investVO.getInvestUserId());
        String benefitBindCode = userBindService.getBindCodeByUserId(lend.getUserId());
        // 调用hfb接口，生成form表单
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        paramMap.put("voteBindCode", bindCode);// 投资人绑定协议
        paramMap.put("benefitBindCode", benefitBindCode);// 借款人绑定协议
        paramMap.put("agentProjectCode", lend.getLendNo());// 项目编号
        paramMap.put("agentProjectName", lend.getTitle());// 项目名称
        paramMap.put("agentBillNo", lendItemNo);// 订单编号
        paramMap.put("voteAmt", investAmount);// 投资金额
        paramMap.put("votePrizeAmt", "0");// 投资奖励金额
        paramMap.put("voteFeeAmt", "0");// 商户手续费
        paramMap.put("projectAmt", lend.getAmount());// 表的总金额
        paramMap.put("note", "");// 投资备注
        paramMap.put("notifyUrl", HfbConst.INVEST_NOTIFY_URL);// 投资成功异步回调路径
        paramMap.put("returnUrl", HfbConst.INVEST_RETURN_URL);// 投资成功同步跳转路径
        paramMap.put("timestamp", RequestHelper.getTimestamp());// 时间戳

        // 验签参数
        paramMap.put("sign", RequestHelper.getSign(paramMap));

        String formStr = FormHelper.buildForm(HfbConst.INVEST_URL, paramMap);

        return formStr;
    }

    /**
     * 投资交易汇付宝回调
     *
     * @param paramMap 投资交易汇付宝回调参数
     */
    @Override
    public void notifyInvest(Map<String, Object> paramMap) {

        // 获取参数
        String agentBillNo = (String) paramMap.get("agentBillNo");
        String voteBindCode = (String) paramMap.get("voteBindCode");
        BigDecimal voteAmt = new BigDecimal((String) paramMap.get("voteAmt"));

        // 更新lend_item，状态已支付
        LendItem lendItem = baseMapper.selectOne(new LambdaQueryWrapper<LendItem>()
                .eq(LendItem::getLendItemNo, agentBillNo));// 根据投标的单号找到lend_item
        Assert.notNull(lendItem, ResponseEnum.PAY_UNIFIEDORDER_ERROR);
        lendItem.setStatus(1);// 已支付
        baseMapper.updateById(lendItem);

        // 更新lend表，已投金额，已投人数
        Lend lend = lendService.getById(lendItem.getLendId());
        lend.setInvestNum(lend.getInvestNum() + 1);
        lend.setInvestAmount(lend.getInvestAmount().add(voteAmt));
        lendService.updateById(lend);

        // 更新user_account，修改投标人的账号冻结金额
        UserAccount userAccount = userAccountMapper.selectOne(new LambdaQueryWrapper<UserAccount>()
                .eq(UserAccount::getUserId, lendItem.getInvestUserId()));
        int i = userAccount.getAmount().compareTo(voteAmt);
        Assert.isTrue(i > 0, ResponseEnum.PAY_UNIFIEDORDER_ERROR);

        LambdaUpdateWrapper<UserAccount> updateWrapper = new LambdaUpdateWrapper<UserAccount>()
                .setSql(" amount = amount - " + voteAmt + ", freeze_amount = freeze_amount + " + voteAmt)
                .eq(UserAccount::getUserId, lendItem.getInvestUserId());
        userAccountMapper.update(null, updateWrapper);

        // 添加交易流水trans_flow表
        TransFlowBO transFlowBO = TransFlowBO.builder()
                .agentBillNo(agentBillNo)
                .bindCode(voteBindCode)
                .amount(voteAmt)
                .transTypeEnum(TransTypeEnum.INVEST_LOCK)
                .memo("投资冻结，投资项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle())
                .build();
        transFlowService.saveTransFlow(transFlowBO);

    }

    /**
     * 获取投资列表信息
     *
     * @param lendId 标的id
     * @param status 标的出借记录状态
     * @return java.util.List<com.hwd.srb.core.pojo.entity.LendItem>
     */
    @Override
    public List<LendItem> getByLendId(Long lendId, int status) {
        LambdaQueryWrapper<LendItem> queryWrapper = new LambdaQueryWrapper<LendItem>()
                .eq(LendItem::getLendId, lendId)
                .eq(LendItem::getStatus, status);
        return baseMapper.selectList(queryWrapper);
    }
}
